

/*	This code computes characteristics-factor betas for stocks, mutual funds and hedge funds, and macro-factor betas for stocks.
Note, I redefine each macro before running the code for each sample, since for stock/mf/hf, 
the saved output data is named differently, observation ID differs. */

options threads cpucount=8 sortsize=32G bufno=8;
dm log 'clear';

%let mainfolder=D:\Dropbox\Characteristics Factors\RFS_Replication\;

libname mylib "&mainfolder.\Data_Cleaned";

proc datasets library=work nolist kill;
run;
quit;

/*	one-factor beta	*/
*	list of factors to keep from factor data. ;
%let factorlist=mktrf rf hml smb_ff5 rmw cma ia roe qmj pmu umd mgmt perf fin pead;

%macro onefactor(factor=);

proc sql;
drop table crsp4,beta1;
quit;

proc sort data=crsp3(keep=permno currentdate date exret &factor) out=crsp4 nodupkey;
by permno currentdate date;
where not missing(&factor) and not missing(currentdate) and not missing(exret);
run;

proc reg data=crsp4 outest=beta1 noprint;
by permno currentdate;
model exret=&factor/ sse;
run;

data beta1;
set beta1;
freq_&factor=_P_ + _EDF_;
keep permno currentdate &factor freq_&factor;
run;

proc sort data=beta1 out=beta1(rename=(currentdate=date &factor=beta1_&factor));
by permno currentdate;
run;

data beta_&factor;
set beta1;
run;

%mend onefactor;
*	Monthly ;
proc sort data=mylib.allfactors(keep=date &factorlist) out=factors;
by date;
run;

%macro beta1(gap=,startn=,endn=,window=);

proc sql;
drop table mylib.beta1_&window;
quit;

%do k=&startn %to &endn;

proc datasets library=work nolist;
save factors;
run;

data crsp;
set mylib.crsp;
where %eval(&gap*(&k-1))<=permno<%eval(&gap*(&k)) and 1950<=year(date)<=2023;
if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & hexcd = 3 & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.55;
else if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & (hexcd = 1 | hexcd =2 ) & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.3;
else if dlret = .S | dlret = .T | dlret = .A | dlret = .P then Ddlret = .;
else DDLRET=DLRET;
if Dlstcd=. or dlstcd=100 THEN ret=rET; 
ELSE ret=ddlret;
date=intnx('month',date,0,'e');
format date yymmddn8.;
keep permno date ret;
Run;

proc sort data=crsp nodupkey;
by _all_;
where not missing(permno) and not missing(date) and not missing(ret);
run;

proc sort data=crsp nodupkey;
by date permno;
run;

data crsp1(drop=ret rf);
merge crsp(in=in1) factors(in=in2);
by date;
if in1 and in2;
exret=ret-rf;
run;

proc sort data=crsp1(keep=permno date) out=monthend nodupkey;
by permno date;
run;

proc sql;
create view crsp2
as select distinct a.permno as permno0,a.date as currentdate,b.*
from monthend(keep=permno date) as a, crsp1 as b 
where a.permno=b.permno and 0<=intck('month',b.date,a.date)<=%eval(&window-1)
group by a.permno,a.date;
quit;

proc sort data=crsp2(drop=permno) out=crsp3(rename=(permno0=permno)) nodupkey;
by permno0 currentdate date;
where not missing(permno0) and not missing(date) and not missing(exret);
run;

%onefactor(factor=smb_ff5);
%onefactor(factor=hml);
%onefactor(factor=rmw);
%onefactor(factor=cma);
%onefactor(factor=pmu);
%onefactor(factor=ia);
%onefactor(factor=roe);
%onefactor(factor=fin);
%onefactor(factor=mgmt);
%onefactor(factor=qmj);
%onefactor(factor=umd);
%onefactor(factor=pead);
%onefactor(factor=perf);

data beta;
merge beta_smb_ff5 beta_hml beta_rmw beta_cma beta_pmu beta_ia beta_roe beta_fin beta_mgmt beta_qmj 
beta_umd beta_pead beta_perf;
by permno date;
run;

proc append data=beta base=mylib.beta1_&window force;
run;

%end;
%mend beta1;
*	93436 permnos in total	;
*options nonotes;
%beta1(gap=2000,startn=6,endn=47,window=60);
*options notes;
********************************************************************************;
*	Daily factors: MOM, PEAD, PERF	;
proc sort data=mylib.allfactors_daily(keep=date &factorlist) out=factors;
by date;
run;

%macro beta2(gap=,startn=,endn=,window=);

proc sql;
drop table mylib.beta2_&window;
quit;

%do k=&startn %to &endn;

proc datasets library=work nolist;
save factors;
run;

dm 'log; clear';
dm 'odsresults; clear';

data crsp;
set mylib.crsp_d;
where %eval(&gap*(&k-1))<=permno<%eval(&gap*(&k)) and 1950<=year(date)<=2023;
if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & hexcd = 3 & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.55;
else if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & (hexcd = 1 | hexcd =2 ) & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.3;
else if dlret = .S | dlret = .T | dlret = .A | dlret = .P then Ddlret = .;
else DDLRET=DLRET;
if Dlstcd=. or dlstcd=100 THEN ret=rET; 
ELSE ret=ddlret;
monthend=intnx('month',date,0,'e');
format monthend yymmddn8.;
keep permno monthend date ret;
Run;

proc sort data=crsp nodupkey;
by _all_;
where not missing(permno) and not missing(date) and not missing(ret);
run;

proc sort data=crsp nodupkey;
by date permno;
run;

data crsp1(drop=ret rf);
merge crsp(in=in1) factors(in=in2);
by date;
if in1 and in2;
exret=ret-rf;
run;

proc sort data=crsp1(keep=permno monthend) out=monthend nodupkey;
by permno monthend;
run;

proc sql;
create view crsp2
as select distinct a.permno as permno0,a.monthend as currentdate,b.*
from monthend(keep=permno monthend) as a, crsp1 as b 
where a.permno=b.permno and 0<=intck('month',b.date,a.monthend)<=%eval(&window-1)
group by a.permno,a.monthend;
quit;

proc sort data=crsp2(drop=permno) out=crsp3(rename=(permno0=permno)) nodupkey;
by permno0 currentdate date;
where not missing(permno0) and not missing(date) and not missing(exret);
run;

%onefactor(factor=umd);
%onefactor(factor=pead);
%onefactor(factor=perf);

data beta;
merge beta_umd beta_pead beta_perf;
by permno date;
run;

%if &window=12 %then %do;

%onefactor(factor=smb_ff5);
%onefactor(factor=hml);
%onefactor(factor=rmw);
%onefactor(factor=cma);
%onefactor(factor=pmu);
%onefactor(factor=ia);
%onefactor(factor=roe);
%onefactor(factor=fin);
%onefactor(factor=mgmt);
%onefactor(factor=qmj);

data beta;
merge beta beta_smb_ff5 beta_hml beta_rmw beta_cma beta_pmu beta_ia beta_roe beta_fin beta_mgmt beta_qmj;
by permno date;
run;

%end;

proc append data=beta base=mylib.beta2_&window force;
run;

%end;
%mend beta2;
*	93436 permnos in total	;
*options nonotes;
%beta2(gap=2000,startn=6,endn=47,window=3);
*options notes;
****************************************************************************************;
****************************************************************************************;
****************************************************************************************;
****************************************************************************************;
****************************************************************************************;


/*	MF sample, mf1 macro is for monthly factors, mf2 macro is for daily factors.*/
proc datasets library=work nolist kill;
run;
quit;
*	list of factors to keep from factor data.;
%let factorlist=mktrf rf hml smb_ff5 rmw cma ia roe qmj pmu umd mgmt perf fin pead;

%macro onefactor(factor=);

proc sql;
drop table crsp4,beta1;
quit;

proc sort data=all4(keep=wficn currentdate date exret &factor) out=crsp4 nodupkey;
by wficn currentdate date;
where not missing(&factor) and not missing(currentdate) and not missing(exret);
run;

proc reg data=crsp4 outest=beta1 noprint;
by wficn currentdate;
model exret=&factor/ sse;
run;

data beta1;
set beta1;
freq_&factor=_P_ + _EDF_;
keep wficn currentdate &factor freq_&factor;
run;

proc sort data=beta1 out=beta1(rename=(currentdate=date &factor=beta1_&factor wficn=permno));
by wficn currentdate;
run;

data beta_&factor;
set beta1;
run;

%mend onefactor;

%macro mf1(ret=,window=);

dm 'log; clear';

proc sql;
drop table mylib.beta1_mf_&window;
quit;

data factors;
set mylib.allfactors(keep=date &factorlist);
date=intnx('month',date,0,'e');
format date yymmddn8.;
run;

proc sort data=factors;
by date;
run;

%do kk=1 %to &lastm;

dm 'odsresults; clear';

proc sort data=all0 out=all1 nodupkey;
by date wficn;
where %eval(&gap*(&kk-1))<fundno<=%eval(&gap*(&kk)) and not missing(wficn) and not missing(date) and not missing(&ret); 
run;

data all2(drop=rf &ret)/view=all2;
merge all1(in=in1) factors(in=in2);
by date;
if in1 and in2;
exret=&ret-rf;
run;

proc sort data=all2(keep=wficn date) out=monthend nodupkey;
by wficn date;
run;

proc sql;
create view all3 
as select a.wficn as wficn0,a.date as currentdate,b.*
from monthend as a left join all2 as b
on a.wficn=b.wficn and 0<=intck('month',b.date,a.date)<=%eval(&window-1)
group by a.wficn,a.date;
quit;

proc sort data=all3(drop=wficn) out=all4(rename=(wficn0=wficn)) nodupkey;
by wficn0 currentdate date;
run;

%onefactor(factor=SMB_ff5);
%onefactor(factor=HML);
%onefactor(factor=RMW);
%onefactor(factor=CMA);
%onefactor(factor=umd);
%onefactor(factor=IA);
%onefactor(factor=ROE);
%onefactor(factor=PMU);
%onefactor(factor=QMJ);
%onefactor(factor=MGMT);
%onefactor(factor=perf);
%onefactor(factor=FIN);
%onefactor(factor=pead);


data beta;
merge beta_smb_ff5 beta_hml beta_rmw beta_cma beta_umd beta_pmu beta_ia beta_roe beta_fin beta_pead beta_qmj beta_mgmt beta_perf;
by permno date;
run;

proc append data=beta base=mylib.beta1_mf_&window force;
run;

proc datasets library=work nolist;
save returns returns1 factors all0;
run;
quit;

%end;
%mend mf1;

%macro mfbeta1;

/*	1. Main specification: monthly one-factor beta	*/
proc sql;
drop table wficn,wficn1,wficn2,wficn3;
quit;

data returns;
set mylib.mf_monthly;
run;

proc sort data=returns out=returns1;
by wficn date;
run;

proc sort data=returns1(keep=wficn) out=wficn nodupkey;
by wficn;
run;

data wficn(rename=(n=fundno));
set wficn;
n+1;
run;

proc sort data=wficn nodupkey;
by wficn;
run;

data all0;
merge returns1(keep=wficn date rret ret) wficn(in=in1);
by wficn;
if in1;
run;

%let gap=1000;

proc sql noprint;
select ceil(max(fundno)/&gap)
into :lastm
from wficn;
quit;

%put &gap &lastm; 

*options nonotes;
%mf1(ret=rret,window=24);
*options notes;

%SYMDEL gap;

%mend mfbeta1;

%mfbeta1;
*************************************************************************************;

/*	Daily factor betas	*/
%macro onefactor(factor=);

proc sql;
drop table crsp4,beta1;
quit;

proc sort data=all4(keep=wficn currentdate date exret &factor) out=crsp4;
by wficn currentdate date;
where not missing(&factor) and not missing(currentdate) and not missing(exret);
run;

proc reg data=crsp4 outest=beta1 noprint;
by wficn currentdate;
model exret=&factor/ sse;
run;

data beta1;
set beta1;
freq_&factor=_P_ + _EDF_;
keep wficn currentdate &factor freq_&factor;
run;

proc sort data=beta1 out=beta1(rename=(currentdate=date &factor=beta1_&factor wficn=permno));
by wficn currentdate;
run;

data beta_&factor;
set beta1;
run;

%mend onefactor;

%macro mf2(ret=,window=);

dm 'log; clear';

proc sql;
drop table mylib.beta2_mf_&window;
quit;

proc sort data=mylib.allfactors_daily(keep=date &factorlist) out=factors;
by date;
run;

%do kk=1 %to &lastm;

dm 'odsresults; clear';

proc sort data=all0 out=all1 nodupkey;
by date wficn;
where %eval(&gap*(&kk-1))<fundno<=%eval(&gap*(&kk)) and not missing(wficn) and not missing(date) and not missing(&ret); 
run;

data all2(drop=rf &ret)/view=all2;
merge all1(in=in1) factors(in=in2);
by date;
if in1 and in2;
exret=&ret-rf;
monthend=intnx('month',date,0,'e');
format monthend yymmddn8.;
run;

proc sort data=all2(keep=wficn monthend) out=monthend nodupkey;
by wficn monthend;
run;

proc sql;
create view all3 
as select a.wficn as wficn0,a.monthend as currentdate,b.*
from monthend(keep=wficn monthend) as a left join all2 as b
on a.wficn=b.wficn and 0<=intck('month',b.date,a.monthend)<=%eval(&window-1)
group by a.wficn,a.monthend;
quit;

proc sort data=all3(drop=wficn) out=all4(rename=(wficn0=wficn)) nodupkey;
by wficn0 currentdate date;
run;

%onefactor(factor=umd);
%onefactor(factor=perf);
%onefactor(factor=pead);

data beta;
merge beta_umd beta_pead beta_perf;
by permno date;
run;

proc append data=beta base=mylib.beta2_mf_&window force;
run;

proc datasets library=work nolist;
save returns2 factors all0;
run;
quit;

%end;
%mend mf2;

%macro mfbeta3;

proc sql;
drop table wficn,wficn1,wficn2,wficn3;
quit;

proc sort data=mylib.mf_daily out=returns2;
by wficn date;
run;

proc sort data=returns2(keep=wficn) out=wficn nodupkey;
by wficn;
run;

data wficn(rename=(n=fundno));
set wficn;
n+1;
run;

proc sort data=wficn nodupkey;
by wficn;
run;

data all0;
merge returns2(keep=wficn date rret ret) wficn(in=in1);
by wficn;
if in1;
run;

%let gap=500;

proc sql noprint;
select ceil(max(fundno)/&gap)
into :lastm
from wficn;
quit;

%put &gap &lastm; 

*ret=rret is gross return adding back expense, ret=ret is net return after subtracting expense;
*options nonotes;
%mf2(ret=rret,window=3);
*options notes;

%SYMDEL gap;

%mend mfbeta3;

%mfbeta3;
******************************************************************************************************;


*	Merge beta with TR filtered data and only keep obs. with number of stocks>=10 in holdings;
%macro tr(inmf=,indata=);

proc sql;
drop table temp,temp1;
quit;

proc sort data = mylib.&indata._mf_24 out=temp nodupkey; 
by permno date; 
run;

data temp1;
merge temp(in=in1) mylib.trmf(keep=wficn date rename=(wficn=permno) in=in2);
by permno date; 
if in1 and in2;
run;

proc sort data = temp1 out=mylib.&indata._mf_24 nodupkey;
by permno date; 
run;

%mend tr;

%tr(indata=beta1);

%macro tr(inmf=,indata=);

proc sql;
drop table temp,temp1;
quit;

proc sort data = mylib.&indata._mf_3 out=temp nodupkey; 
by permno date; 
run;

data temp1;
merge temp(in=in1) mylib.trmf(keep=wficn date rename=(wficn=permno) in=in2);
by permno date; 
if in1 and in2;
run;

proc sort data = temp1 out=mylib.&indata._mf_3 nodupkey;
by permno date; 
run;

%mend tr;

%tr(indata=beta2);
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;


/*	HF sample	*/
*	list of factors to keep from factor data. ;
%let factorlist=mktrf rf hml smb_ff5 rmw cma ia roe qmj pmu umd mgmt perf fin pead;

%macro onefactor(factor=);

proc sql;
drop table crsp4,beta1;
quit;

proc sort data=all4(keep=wficn currentdate date exret &factor) out=crsp4 nodupkey;
by wficn currentdate date;
where not missing(&factor) and not missing(currentdate) and not missing(exret);
run;

proc reg data=crsp4 outest=beta1 noprint;
by wficn currentdate;
model exret=&factor/ sse;
run;

data beta1;
set beta1;
freq_&factor=_P_ + _EDF_;
keep wficn currentdate &factor freq_&factor;
run;

proc sort data=beta1 out=beta1(rename=(currentdate=date &factor=beta1_&factor wficn=permno));
by wficn currentdate;
run;

data beta_&factor;
set beta1;
run;

%mend onefactor;

%macro hf1(ret=,window=);

dm 'log; clear';

proc sql;
drop table mylib.beta1_hf_&window;
quit;

data factors;
set mylib.allfactors(keep=date &factorlist);
date=intnx('month',date,0,'e');
format date yymmddn8.;
run;

proc sort data=factors;
by date;
run;

%do kk=1 %to &lastm;

dm 'odsresults; clear';

proc sort data=all0 out=all1 nodupkey;
by date wficn;
where %eval(&gap*(&kk-1))<fundno<=%eval(&gap*(&kk)) and not missing(wficn) and not missing(date) and not missing(&ret); 
run;

data all2(drop=rf &ret)/view=all2;
merge all1(in=in1) factors(in=in2);
by date;
if in1 and in2;
exret=&ret-rf;
run;

proc sort data=all2(keep=wficn date) out=monthend nodupkey;
by wficn date;
run;

proc sql;
create view all3 
as select a.wficn as wficn0,a.date as currentdate,b.*
from monthend as a left join all2 as b
on a.wficn=b.wficn and 0<=intck('month',b.date,a.date)<=%eval(&window-1)
group by a.wficn,a.date;
quit;

proc sort data=all3(drop=wficn) out=all4(rename=(wficn0=wficn)) nodupkey;
by wficn0 currentdate date;
run;

%onefactor(factor=SMB_ff5);
%onefactor(factor=HML);
%onefactor(factor=RMW);
%onefactor(factor=CMA);
%onefactor(factor=umd);
%onefactor(factor=IA);
%onefactor(factor=ROE);
%onefactor(factor=PMU);
%onefactor(factor=QMJ);
%onefactor(factor=MGMT);
%onefactor(factor=perf);
%onefactor(factor=FIN);
%onefactor(factor=pead);


data beta;
merge beta_smb_ff5 beta_hml beta_rmw beta_cma beta_umd beta_pmu beta_ia beta_roe beta_fin beta_pead beta_qmj beta_mgmt beta_perf;
by permno date;
run;

proc append data=beta base=mylib.beta1_hf_&window force;
run;

proc datasets library=work nolist;
save returns returns1 factors all0;
run;
quit;

%end;
%mend hf1;

%macro hfbeta1;

proc sql;
drop table wficn,wficn1,wficn2,wficn3;
quit;

data returns;
set mylib.hf_returns;
date=intnx('month',date,0,'e');
format date yymmddn8.;
run;

proc sort data=returns out=returns1;
by wficn date;
run;

proc sort data=returns1(keep=wficn) out=wficn nodupkey;
by wficn;
run;

data wficn(rename=(n=fundno));
set wficn;
n+1;
run;

proc sort data=wficn nodupkey;
by wficn;
run;

data all0;
merge returns1(keep=wficn date rret) wficn(in=in1);
by wficn;
if in1;
run;

%let gap=1000;

proc sql noprint;
select ceil(max(fundno)/&gap)
into :lastm
from wficn;
quit;

%put &gap &lastm; 

*options nonotes;
%hf1(ret=rret,window=24);
%SYMDEL gap;

%mend hfbeta1;

%hfbeta1;
*************************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;
******************************************************************************************************;




*	Macro factors	;
/*	Compute single-factor macro beta, tfp is qtrly and use past 8 years of qtrly data to compute beta, others are all monthly and use past 5 years, 
for all betas, skip one period to ensure data is available	*/
proc sort data=mylib.factors_macro out=factors;
by date;
run;

%macro onefactor(factor=);

proc sql;
drop table crsp4,beta1,beta2,beta3;
quit;

proc sort data=crsp3(keep=permno currentdate date ret &factor) out=crsp4 nodupkey;
by permno currentdate date;
where not missing(&factor) and not missing(currentdate) and not missing(ret);
run;

proc reg data=crsp4 outest=beta1 noprint;
by permno currentdate;
model ret=&factor/ sse;
run;

data beta1;
set beta1;
freq_&factor=_P_ + _EDF_;
&factor._ret=&factor;
keep permno currentdate &factor._ret freq_&factor;
run;

proc sort data=beta1 out=beta1(rename=(currentdate=date &factor._ret=beta1_&factor._ret));
by permno currentdate;
run;

data beta_&factor;
set beta1;
run;

%mend onefactor;
*	monthly factor	;
%macro beta2(gap=,startn=,endn=,window=);

proc sql;
drop table mylib.beta2_macro_intraday_&window;
quit;

%do k=&startn %to &endn;

proc datasets library=work nolist;
save factors;
run;

data crsp1;
set mylib.crsp;
where %eval(&gap*(&k-1))<=permno<%eval(&gap*(&k)) and 1950<=year(date)<=2023;
if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & hexcd = 3 & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.55;
else if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & (hexcd = 1 | hexcd =2 ) & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.3;
else if dlret = .S | dlret = .T | dlret = .A | dlret = .P then Ddlret = .;
else DDLRET=DLRET;
if Dlstcd=. or dlstcd=100 THEN ret=rET; 
ELSE ret=ddlret;
date=intnx('month',date,0,'e');
format date yymmddn8.;
keep permno date ret;
Run;

proc sort data=crsp1 nodupkey;
by _all_;
where not missing(permno) and not missing(date) and not missing(ret);
run;

proc sort data=crsp1 nodupkey;
by date permno;
run;

data crsp1(drop=ret rename=(ret1=ret));
merge crsp1(in=in1) factors(keep=date rf in=in2);
by date;
if in1 and in2;
ret1=ret-rf;
run;

proc sort data=crsp1 nodupkey;
by date permno;
run;

data crsp1;
merge crsp1(in=in1) factors(drop=tfp in=in2);
by date;
if in1 and in2;
run;

proc sort data=crsp1(keep=permno date) out=monthend nodupkey;
by permno date;
run;
*	need to gap one period to compute beta, so I leave one month here, and this date has the same timing as the lagme data in the future	;
proc sql;
create view crsp2
as select distinct a.permno as permno0,a.date as currentdate,b.*
from monthend(keep=permno date) as a, crsp1 as b 
where a.permno=b.permno and 1<=intck('month',b.date,a.date)<=%eval(&window)
group by a.permno,a.date;
quit;

proc sort data=crsp2(drop=permno) out=crsp3(rename=(permno0=permno)) nodupkey;
by permno0 currentdate date;
where not missing(permno0) and not missing(date) and not missing(ret);
run;

%onefactor(factor=	con );
%onefactor(factor=	ipg );
%onefactor(factor=	term);
%onefactor(factor=	def	);
%onefactor(factor=	ui	);
%onefactor(factor=	dei	);
%onefactor(factor=	vol	);
%onefactor(factor=	mkt	);
%onefactor(factor=	lab	);

data beta;
merge beta_con beta_ipg beta_term beta_def beta_ui beta_dei beta_vol beta_mkt beta_lab;
by permno date;
run;

proc append data=beta base=mylib.beta2_macro_intraday_&window force;
run;

%end;
%mend beta2;
*options nonotes;
%beta2(gap=10000,startn=2,endn=10,window=60);
*options notes;

*	qtrly factor	;
%macro beta2(gap=,startn=,endn=,window=);

proc sql;
drop table mylib.beta2_macro_intraday_&window;
quit;

%do k=&startn %to &endn;

proc datasets library=work nolist;
save factors;
run;

data crsp1;
set mylib.crsp;
where %eval(&gap*(&k-1))<=permno<%eval(&gap*(&k)) and 1950<=year(date)<=2023;
if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & hexcd = 3 & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.55;
else if (dlstcd = 500 | dlstcd <= 584 and dlstcd >= 520) & (hexcd = 1 | hexcd =2 ) & (dlret = .S | dlret = .T | dlret = .P) then Ddlret = -.3;
else if dlret = .S | dlret = .T | dlret = .A | dlret = .P then Ddlret = .;
else DDLRET=DLRET;
if Dlstcd=. or dlstcd=100 THEN ret=rET; 
ELSE ret=ddlret;
date=intnx('month',date,0,'e');
format date yymmddn8.;
keep permno date ret;
Run;

proc sort data=crsp1 nodupkey;
by _all_;
where not missing(permno) and not missing(date) and not missing(ret);
run;

proc sort data=crsp1 nodupkey;
by date permno;
run;

data crsp1(drop=ret rename=(ret1=ret));
merge crsp1(in=in1) factors(keep=date rf in=in2);
by date;
if in1 and in2;
ret1=ret-rf;
run;

proc sort data=crsp1 nodupkey;
by date permno;
run;

data crsp1;
set crsp1;
date=intnx('qtr',date,0,'e');
format date yymmddn8.;
logret=log(1+ret);
keep permno date logret;
run;

proc sort data=crsp1;
by permno date;
run;

proc means data=crsp1 noprint;
by permno date;
var logret;
output out=crsp1_1(drop=_type_) sum=logret;
run;

data crsp1_1;
set crsp1_1;
where _freq_=3;
ret=exp(logret)-1;
keep permno date ret;
run;

proc sort data=crsp1_1;
by date permno;
run;

data crsp1_1;
merge crsp1_1(in=in1) factors(keep=date tfp in=in2);
by date;
if in1 and in2;
run;

proc sort data=crsp1_1(keep=permno date) out=monthend nodupkey;
by permno date;
run;

proc sql;
create view crsp2
as select distinct a.permno as permno0,a.date as currentdate,b.*
from monthend(keep=permno date) as a, crsp1_1 as b 
where a.permno=b.permno and 1<=intck('qtr',b.date,a.date)<=%eval(&window)
group by a.permno,a.date;
quit;

proc sort data=crsp2(drop=permno) out=crsp3(rename=(permno0=permno)) nodupkey;
by permno0 currentdate date;
where not missing(permno0) and not missing(date) and not missing(ret);
run;

%onefactor(factor=tfp);

data beta;
set beta_tfp;
run;

proc append data=beta base=mylib.beta2_macro_intraday_&window force;
run;

%end;
%mend beta2;
*options nonotes;
%beta2(gap=10000,startn=2,endn=10,window=24);
**************************************************************************************************************;
*	expand qtrly to monthly	;
data temp1;
set mylib.beta2_macro_intraday_24;
date=intnx('month',date,1,'e');
format date yymmddn8.;
run;

data temp2;
set mylib.beta2_macro_intraday_24;
date=intnx('month',date,2,'e');
format date yymmddn8.;
run;

data temp3;
set mylib.beta2_macro_intraday_24 temp1 temp2;
run;

proc sort data=temp3;
by permno date;
run;
**************************************************************************************************************;
*	combine the monthly and qtrly betas together and save in the monthly data;
data temp4;
merge mylib.beta2_macro_intraday_60 temp3;
by permno date;
run;

proc sort data=temp4 out=mylib.beta_macro_intraday;
by permno date;
run;
**************************************************************************************************************;




